#pragma once

#include<iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<sys/epoll.h>

#include"Log.hpp"
#include"Connection.hpp"
#include"Reactor.hpp"

//数据已经读取，调用这个函数进行数据处理
void handlefunc(ConnectionSpace::Connection& conn)
{
    cout<<conn.GetInbuf();
}

void Write(ConnectionSpace::Connection& conn)
{
    while(true)
    {
        errno=0;
        int n=write(conn.GetFd(),conn.GetOutbuf().c_str(),conn.GetOutbuf().size());
        if(n>0)
        {
            conn.GetOutbuf().erase(0,n);
            continue;
        }
        else if(0==n)
        {
            break;
        }
        else
        {
            if(EWOULDBLOCK==errno||EAGAIN==errno)
            {
                Log(DEBUG,"write buf is full\n");
                break;
            }
            else if(EINTR==errno)
            {
                Log(DEBUG,"write was interrupted by signal\n");
                continue;
            }
            else
            {
                Log(ERROR,"write error\n");
                return;
            }
        }
    }

    //走到这里要么数据发送完毕，要么发送缓冲区满
    if(conn.IsOutBufEmpty())
    {
        Log(DEBUG,"write successfully\n");
        //可能开启了写事件监视，需要关闭
        uint32_t events=conn.GetEvents()&(~EPOLLOUT);
        conn._reactor->Modify(conn.GetFd(),events);
    }
    else
    {
        //需要开启写事件监视以将数据写完
        uint32_t events=conn.GetEvents()|(~EPOLLOUT);
        conn._reactor->Modify(conn.GetFd(),events);
    }
}

void Read(ConnectionSpace::Connection & conn)
{
    while(true)
    {
        errno=0;
        char buf[1024];
        int n=read(conn.GetFd(),buf,sizeof(buf)-1);
        if(n>0)
        {
            buf[n]=0;
            conn.AppendInBuf(buf);
            continue;
        }
        else
        {
            if(EWOULDBLOCK==errno||EAGAIN==errno)
            {
                Log(DEBUG,"read successfully\n");
                handlefunc(conn);
                return;
            }
            else if(EINTR==errno)
            {
                Log(DEBUG,"read interrupted by signal\n");
                continue;
            }
            else
            {
                Log(ERROR,"read error\n");
                return;
            }
        }
    }
}

void Except(ConnectionSpace::Connection & conn)
{
    Log(DEBUG, "client quit : %d\n",conn.GetFd());
    conn._reactor->Remove(conn.GetFd());
}

void AcceptClientLink(ConnectionSpace::Connection & conn)
{
    while(true)
    {
        errno=0;
        struct sockaddr_in client;
        bzero(&client,sizeof(client));
        socklen_t len=sizeof(client);
        int sockfd=accept(conn.GetFd(),(struct sockaddr*)&client,&len);
        if(sockfd>=0)
        {
            uint32_t events=EPOLLIN;
            conn._reactor->Add(conn.GetFd(),events);
            continue;
        }
        else
        {
            if(EWOULDBLOCK==errno||EAGAIN==errno)
            {
                Log(DEBUG,"get all link successfully\n");
                return;
            }
            else if(EINTR==errno)
            {
                Log(DEBUG,"accept was interrupted by signal\n");
                continue;
            }
            else
            {
                Log(ERROR,"accept error\n");
                return;
            }
        }
    }
}